#include "com_mirror_rtcp.h"
#include "com_mirror_surface.h"
using namespace android;

//free rtcp handle for close socket
void Free_Rtcp_Udp(HI_RTCP_Handler *rtcphandle);

/*RTCP init */
HI_S32 Init_Rtcp_Udp(HI_RTCP_Handler *rtcphandle,const char * clientaddress, unsigned short clientport, unsigned short localport)
{
  HI_S32 keepalive=1;
  HI_S32 s32Ret = HI_FAILURE;

  if(NULL == rtcphandle)
  {
     LOGE("rtcphandle is null");
     return s32Ret;
  }
  rtcphandle->rtcp_sock = -1;

  strncpy(rtcphandle->udpparams.clientaddress, clientaddress ,ADDRESS_CHAR_LENGTH);
  rtcphandle->udpparams.portbase= clientport;
  rtcphandle->udpparams.portlocal = localport;

  //init rtcphead
  bzero(&rtcphandle->rtcphead,sizeof(rtcphandle->rtcphead));
  rtcphandle->rtcphead.packet_type = RTCP_APP;

  rtcphandle->rtcp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  if(rtcphandle->rtcp_sock < 0)
  {
      LOGE("socket error");
      return HI_FAILURE;
  }

  bzero(&rtcphandle->udpparams.s_addr, sizeof(rtcphandle->udpparams.s_addr));
  rtcphandle->udpparams.s_addr.sin_family = AF_INET;
  rtcphandle->udpparams.s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  rtcphandle->udpparams.s_addr.sin_port = htons(rtcphandle->udpparams.portlocal);
  s32Ret = setsockopt(rtcphandle->rtcp_sock,SOL_SOCKET ,SO_REUSEADDR,&keepalive,sizeof(keepalive));
  s32Ret = bind(rtcphandle->rtcp_sock, (struct sockaddr *)((void*)&(rtcphandle->udpparams.s_addr)),sizeof(rtcphandle->udpparams.s_addr));

  if(s32Ret < 0)
  {
      LOGE("RTCP bind %d error\n",rtcphandle->udpparams.portlocal);
      return HI_FAILURE;
  }

   //socket
   bzero(&rtcphandle->udpparams.c_addr, sizeof(rtcphandle->udpparams.c_addr));
   rtcphandle->udpparams.c_addr.sin_family = AF_INET;

   if(inet_pton(AF_INET, rtcphandle->udpparams.clientaddress, &rtcphandle->udpparams.c_addr.sin_addr) <= 0)
   {
       LOGE("inet_pton error for %s\n",rtcphandle->udpparams.clientaddress);
       return HI_FAILURE;
   }

   rtcphandle->udpparams.c_addr.sin_port = htons(rtcphandle->udpparams.portbase);
   return HI_SUCCESS;
}


/*RTCPHandle Deinit*/
HI_S32 DeInit_Rtcp_Udp(HI_RTCP_Handler *rtcphandle)
{
  if(NULL != rtcphandle)

  {
    close(rtcphandle->rtcp_sock);
    Free_Rtcp_Udp(rtcphandle);
  }
  return HI_SUCCESS;
}

/*RTCPHandle free*/
void Free_Rtcp_Udp(HI_RTCP_Handler *rtcphandle)
{
  if(NULL != rtcphandle)
  {
    free(rtcphandle);
  }
}

/*RTCP Send*/
HI_S32 Send_Rtcp_Udp(HI_RTCP_Handler *rtcphandle)
{
    if(NULL == rtcphandle)
    {
        LOGE("rtcphandle is null");
        return HI_FAILURE;
    }
    if(-1 == rtcphandle->rtcp_sock)

    {
        LOGE("rtcp socket is invalide");
        return HI_FAILURE;
    }

    if(sendto(rtcphandle->rtcp_sock,(unsigned char*)(&rtcphandle->rtcppacket),RTCP_PACKET_LENGTH,0,
        (struct sockaddr *)((void*)&rtcphandle->udpparams.c_addr),
        sizeof(rtcphandle->udpparams.c_addr)) < 0)
    {
        LOGE("send error");
        return HI_FAILURE;
    }
    return HI_SUCCESS;
}

/*cal weight lost num*/
HI_S32 Cal_weighted_lost_num(HI_S32 curLostNum,HI_S32 lastLostNum)
{
    return (int)((1-RTCP_LOST_NUM_WEIGHT)*lastLostNum + RTCP_LOST_NUM_WEIGHT*curLostNum);
}
